package com.boilermaker.lotterysystem.controller;

import com.boilermaker.lotterysystem.common.errorcode.ControllerErrorCodeConstants;
import com.boilermaker.lotterysystem.common.exception.ControllerException;
import com.boilermaker.lotterysystem.common.pojo.CommonResult;
import com.boilermaker.lotterysystem.common.utils.JacksonUtil;
import com.boilermaker.lotterysystem.controller.param.UserPasswordLoginParam;
import com.boilermaker.lotterysystem.controller.param.UserRegisterParam;
import com.boilermaker.lotterysystem.controller.param.UserVerificationCodeLoginParam;
import com.boilermaker.lotterysystem.controller.vo.UserInfoVO;
import com.boilermaker.lotterysystem.controller.vo.UserLoginVO;
import com.boilermaker.lotterysystem.controller.vo.UserRegisterVO;
import com.boilermaker.lotterysystem.service.UserService;
import com.boilermaker.lotterysystem.service.VerificationCodeService;
import com.boilermaker.lotterysystem.service.dto.UserInfoDTO;
import com.boilermaker.lotterysystem.service.dto.UserLoginDTO;
import com.boilermaker.lotterysystem.service.dto.UserRegisterDTO;
import com.boilermaker.lotterysystem.service.enums.UserIdentityEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.stream.Collectors;


@RestController
@Slf4j
public class UserController {

    /**
     * 人员服务注入
     */
    @Autowired
    private UserService userService;

    /**
     * 验证码服务注入
     */
    @Autowired
    private VerificationCodeService verificationCodeService;

    /**
     * 注册 // TODO:注册是针对管理员还是普通用户？
     *
     * @param param
     * @return
     */
    @RequestMapping("/register")
    public CommonResult<UserRegisterVO> userRegister(@Validated @RequestBody UserRegisterParam param) {
        log.info("userRegister UserRegisterParam : {}", JacksonUtil.writeValueAsString(param));

        UserRegisterDTO userRegisterDTO = userService.register(param);

        return CommonResult.success(convertUserRegisterDtoToVo(userRegisterDTO));
    }

    /**
     * 发送邮箱验证码
     */
    @RequestMapping("/verification-code/send")
    public CommonResult<Boolean> sendVerificationCode(String loginMail) {
        log.info("sendVerificationCode mail:{}", loginMail);

        verificationCodeService.sendVerificationCode(loginMail);

        return CommonResult.success(Boolean.TRUE);
    }

    /**
     * 密码登录
     */
    @RequestMapping("/password/login")
    public CommonResult<UserLoginVO> userPasswordLogin(
            @Validated @RequestBody UserPasswordLoginParam param) {
        log.info("userPasswordLogin UserPasswordLoginParam:{}",
                JacksonUtil.writeValueAsString(param));

        UserLoginDTO userLoginDTO = userService.login(param);

        return CommonResult.success(convertUserLoginDtoToVo(userLoginDTO));
    }

    /**
     * 验证码登录
     */
    @RequestMapping("/verification-code/login")
    public CommonResult<UserLoginVO> userVerificationCodeLogin(
            @Validated @RequestBody UserVerificationCodeLoginParam param) {
        log.info("userVerificationCodeLogin UserVerificationCodeLoginParam:{}",
                JacksonUtil.writeValueAsString(param));

        UserLoginDTO userLoginDTO = userService.login(param);

        return CommonResult.success(convertUserLoginDtoToVo(userLoginDTO));
    }

    /**
     * 根据身份查询人员列表
     *
     * @param identity: 受管控的身份标识，若为空则不限身份
     * @return: 列表（内部为用户的全属性）
     */
    @RequestMapping("/base-user/find-list")
    public CommonResult<List<UserInfoVO>> findUserInfoByIdentity(String identity) {
        log.info("findUserInfoByIdentity identity:{}", identity);

        List<UserInfoDTO> dtoList = userService.findUserInfoByIdentity(UserIdentityEnum.forName(identity));

        return CommonResult.success(convertUserInfoDtoToVo(dtoList));
    }

    /**
     * 将 DTO 转换为 VO。DTO 仅用于传输业务数据，而 VO 站在前端需求角度封装数据。
     *
     * @param dto
     * @return
     */
    private UserRegisterVO convertUserRegisterDtoToVo(UserRegisterDTO dto) {

        if (dto == null) {
            throw new ControllerException(ControllerErrorCodeConstants.REGISTER_ERROR);
        }

        UserRegisterVO vo = new UserRegisterVO();
        vo.setUserId(dto.getUserId());

        return vo;
    }

    private UserLoginVO convertUserLoginDtoToVo(UserLoginDTO dto) {

        if (dto == null) {
            throw new ControllerException(ControllerErrorCodeConstants.LOGIN_ERROR);
        }

        UserLoginVO vo = new UserLoginVO();
        vo.setIdentity(dto.getIdentity().name());
        vo.setToken(dto.getToken());

        return vo;
    }

    private List<UserInfoVO> convertUserInfoDtoToVo(List<UserInfoDTO> dtoList) {
        if (CollectionUtils.isEmpty(dtoList)) {
            return List.of();
        }

        return dtoList.stream()
                .map(userDTO -> {
                    UserInfoVO result = new UserInfoVO();
                    result.setUserId(userDTO.getUserId());
                    result.setUserName(userDTO.getUserName());
                    result.setIdentity(userDTO.getIdentity().name());
                    return result;
                }).collect(Collectors.toList());
    }
}
